﻿using AutoMapper;
using Microsoft.EntityFrameworkCore;
using QMERP.Domain.Dtos;
using QMERP.Domain.Entities;
using QMERP.Domain.Enums;
using QMERP.Infrastructure.CustomException;
using QMERP.Infrastructure.EFCore;
using QMERP.Infrastructure.EFCore.Extensions;
using QMERP.Infrastructure.Extensions;
using QMERP.Infrastructure.Security;
using System.Data;

namespace QMERP.Application.Services
{
    public class TransferOrderService : ITransferOrderService
    {
        private readonly IMapper _mapper;
        private readonly QMERPDbContext _db;
        private readonly ISerialNumberService _serialNumberSvc;
        private readonly ICurrentUser _currentUser;
        private IServiceProvider _serviceProvider;
        public TransferOrderService(IMapper mapper, QMERPDbContext db, ISerialNumberService serialNumberSvc, ICurrentUser currentUser, IServiceProvider serviceProvider)
        {
            _mapper = mapper;
            _db = db;
            _serialNumberSvc = serialNumberSvc;
            _currentUser = currentUser;
            _serviceProvider = serviceProvider;
        }
        /// <summary>
        /// 调拨单窗体
        /// </summary>
        /// <returns></returns>
        public async Task<PageResponse<TransferOrderResponse>> Query(PageRequest<TransferOrderRequest> request)
        {
            var response = new PageResponse<TransferOrderResponse>();
            var query = Where(request);
            var list = await query.Paging(request.PageIndex, request.PageSize).ToListAsync();
            response.TotalCount = await query.CountAsync();
            response.PageIndex = request.PageIndex;
            response.PageSize = request.PageSize;
            response.List = _mapper.Map<List<TransferOrderResponse>>(list);
            return response;
        }
        /// <summary>
        /// 获取id的调拨单详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<TransferOrderResponse> Detail(long id)
        {
            var model = await _db.TransferOrder
                .Include(x => x.TransferOrderDetails).ThenInclude(x => x.TransferOrderDetail_LensDetails)
                .Include(x => x.TransferOrderDetails).ThenInclude(x => x.OutWarehouse)
                .Include(x => x.TransferOrderDetails).ThenInclude(x => x.InWarehouse)
                .Include(x => x.TransferOrderDetails).ThenInclude(x => x.Lens).AsNoTracking().FindByIdAsync(id);
            var response = _mapper.Map<TransferOrderResponse>(model);
            return response;
        }
        /// <summary>
        /// 调拨单保存
        /// </summary>
        /// <param name="request"></param>
        /// <param name="isCheck"></param>
        /// <returns></returns>
        /// <exception cref="ApiException"></exception>
        public async Task<TransferOrderResponse> Save(TransferOrderSaveRequest request, bool isCheck = false)
        {
            for (int i = 0; i < request.TransferOrderDetails.Count; i++)
            {
                string col = $"第{i + 1}行:";
                var detail = request.TransferOrderDetails[i];

                if (detail.OutWarehouseId == detail.InWarehouseId)
                    throw new ApiException($"{col}调出仓库不能和调入仓库一样!");

                if (detail.LensDetails.Count <= 0)
                    throw new ApiException($"{col}请导入XY表!");

                if (detail.LensDetails.Sum(s => s.Qty) <= 0)
                    throw new ApiException($"{col}XY表总片数为0,请检查!");

                var stock = await _db.Stock.GetByWarehouseLens(detail.OutWarehouseId, detail.LensId);

                if (!detail.LensDetails.InRange(_mapper.Map<LensResponse>(stock.Lens)))
                    throw new ApiException($"{col}XY表度数超出镜种范围!");

                detail.LensDetails = detail.LensDetails.Where(x => x.Qty > 0).ToList();

                foreach (var lensDetail in detail.LensDetails)
                {
                    var stockDetail = stock.GetByRange(lensDetail.DegreesType, lensDetail.SPH, lensDetail.CYL);
                    if (stockDetail.Qty - lensDetail.Qty < 0)
                    {
                        throw new ApiException($"{col}的调出仓库{stock.Warehouse?.Code}镜种{stock.Lens?.SalesLensCode}度数SPH:{lensDetail.SPH},CYL{lensDetail.CYL}库存片数不足扣库");
                    }
                }
            }

            TransferOrder? model;
            if (request.Id == null)
            {
                string number = await _serialNumberSvc.GetSerialNumber(SerialNumberTypeEnum.TransferOrder);
                model = _mapper.Map<TransferOrder>(request);
                model.Number = number;
                model.Status = TransferOrderStatusEnum.Pending.ToString();
                await _db.AddAsync(model);
            }
            else
            {
                model = await _db.TransferOrder.Include(x => x.TransferOrderDetails).FindByIdAsync(request.Id.Value);
                if (model == null)
                    throw new ApiException("调拨单不存在!");
                model.Remark = request.Remark;
                model.TransferOrderDetails = _mapper.Map<List<TransferOrderDetail>>(request.TransferOrderDetails);
            }
            await _db.SaveChangesAsync();
            if (isCheck)
            {
                model = await _db.TransferOrder
                  .Include(x => x.TransferOrderDetails).ThenInclude(x => x.TransferOrderDetail_LensDetails)
                  .Include(x => x.TransferOrderDetails).ThenInclude(x => x.OutWarehouse)
                  .Include(x => x.TransferOrderDetails).ThenInclude(x => x.InWarehouse)
                  .Include(x => x.TransferOrderDetails).ThenInclude(x => x.Lens).FindByIdAsync(model.Id);
                if (model != null)
                {
                    await Check(model);
                    await _db.SaveChangesAsync();
                }
            }
            return _mapper.Map<TransferOrderResponse>(model);
        }
        /// <summary>
        /// 调拨单审核
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task Check(long[] ids)
        {
            if (ids == null)
                throw new ApiException("id不能为空!");

            var list = await _db.TransferOrder.Include(x => x.TransferOrderDetails).Where(x => ids.Contains(x.Id)).ToListAsync();
            foreach (var order in list)
            {
                if (order.Status != TransferOrderStatusEnum.Pending.ToString())
                    throw new ApiException($"调拨单{order.Number}不能审核!");
                await Check(order);
            }
            await _db.SaveChangesAsync();
        }
        /// <summary>
        /// 调拨单弃审
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task UnCheck(long[] ids)
        {
            if (ids == null)
                throw new ApiException("id不能为空!");

            var list = await _db.TransferOrder.Where(x => ids.Contains(x.Id)).ToListAsync();
            foreach (var order in list)
            {
                if (order.Status != TransferOrderStatusEnum.Receive.ToString())
                    throw new ApiException($"调拨单{order.Number}不能弃审!");

                if (await _db.LeaveStockOrder.AnyAsync(x => x.BusinessOrderType == LeaveStockBusinessOrderTypeEnum.TransferOrder.ToString() && x.BusinessOrderId == order.Id && x.Status != LeaveStockOrderStatusEnum.Canceled.ToString()))
                    throw new ApiException($"调拨单{order.Number}不能弃审,已添加出库单!");

                order.Status = TransferOrderStatusEnum.Pending.ToString();
                order.CheckedBy = null;
                order.CheckedByName = null;
                order.CheckedOn = null;
            }
            await _db.SaveChangesAsync();
        }
        /// <summary>
        /// 调拨单取消
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task Cancel(long[] ids)
        {
            if (ids == null)
                throw new ApiException("id不能为空!");

            var list = await _db.TransferOrder.Where(x => ids.Contains(x.Id)).ToListAsync();
            foreach (var order in list)
            {
                if (order.Status != TransferOrderStatusEnum.Pending.ToString() && order.Status != TransferOrderStatusEnum.Receive.ToString())
                    throw new ApiException($"调拨单{order.Number}不能取消!");

                if (await _db.LeaveStockOrder.AnyAsync(x => x.BusinessOrderType == LeaveStockBusinessOrderTypeEnum.TransferOrder.ToString() && x.BusinessOrderId == order.Id && x.Status != LeaveStockOrderStatusEnum.Canceled.ToString()))
                    throw new ApiException($"调拨单{order.Number}不能取消,已添加出库单!");

                order.Status = TransferOrderStatusEnum.Canceled.ToString();
            }
            await _db.SaveChangesAsync();
        }

        /// <summary>
        /// 获取调拨单主要信息列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<List<TransferOrderMainInfoResponse>> GetTransferOrderMainInfos(PageRequest<TransferOrderRequest> request)
        {
            var orders = await Where(request).ToListAsync();
            var details = orders.SelectMany(s => s.TransferOrderDetails).ToList();
            return _mapper.Map<List<TransferOrderMainInfoResponse>>(details);
        }

        private IQueryable<TransferOrder> Where(PageRequest<TransferOrderRequest> request)
        {
            IQueryable<TransferOrder> query = _db.TransferOrder
                .Include(x => x.TransferOrderDetails).ThenInclude(x => x.TransferOrderDetail_LensDetails)
                .Include(x => x.TransferOrderDetails).ThenInclude(x => x.OutWarehouse)
                .Include(x => x.TransferOrderDetails).ThenInclude(x => x.InWarehouse)
                .Include(x => x.TransferOrderDetails).ThenInclude(x => x.Lens).AsNoTracking();
            if (!request.Query.Number.IsNullOrWhiteSpace())
            {
                query = query.Where(x => x.Number.Contains(request.Query.Number!));
            }
            if (!request.Query.CreatedByName.IsNullOrWhiteSpace())
            {
                query = query.Where(x => x.CreatedByName.Contains(request.Query.CreatedByName!));
            }
            if (request.Query.CreatedOnStart != null)
            {
                query = query.Where(x => x.CreatedOn >= request.Query.CreatedOnStart.Value.ToStart());
            }
            if (request.Query.CreatedOnEnd != null)
            {
                query = query.Where(x => x.CreatedOn <= request.Query.CreatedOnEnd.Value.ToEnd());
            }
            if (!request.Query.Status.IsNullOrWhiteSpace())
            {
                query = query.Where(x => x.Status == request.Query.Status);
            }
            if (request.Query.OutWarehouseId != null)
            {
                query = query.Where(x => x.TransferOrderDetails.Select(s => s.OutWarehouseId).Contains(request.Query.OutWarehouseId.Value));
            }
            if (request.Query.InWarehouseId != null)
            {
                query = query.Where(x => x.TransferOrderDetails.Select(s => s.InWarehouseId).Contains(request.Query.InWarehouseId.Value));
            }
            if (request.Query.LensId != null)
            {
                query = query.Where(x => x.TransferOrderDetails.Select(s => s.LensId).Contains(request.Query.LensId.Value));
            }
            //if (request.Query.Status == TransferOrderStatusEnum.Pending.ToString())
            //{
            //    query = query.OrderByDescending(x => x.CreatedOn);
            //}
            //else if (request.Query.Status == TransferOrderStatusEnum.Receive.ToString())
            //{
            //    query = query.OrderByDescending(x => x.CheckedOn);
            //}
            //else if (request.Query.Status == TransferOrderStatusEnum.AllReceived.ToString())
            //{
            //    query = query.OrderByDescending(x => x.FinishedOn);
            //}
            //else
            //{
            //    query = query.OrderByDescending(x => x.UpdatedOn);
            //}
            query = query.OrderByDescending(x => x.CreatedOn);
            return query;
        }
        private async Task Check(TransferOrder order)
        {
            foreach (var detail in order.TransferOrderDetails)
            {
                var stock = await _db.Stock.GetByWarehouseLens(detail.OutWarehouseId, detail.LensId);
                foreach (var lensDetail in detail.TransferOrderDetail_LensDetails)
                {
                    var stockDetail = stock.GetByRange(lensDetail.DegreesType, lensDetail.SPH, lensDetail.CYL);
                    if (stockDetail.Qty - lensDetail.Qty < 0)
                    {
                        throw new ApiException($"调拨单号{order.Number}的调出仓库{detail.OutWarehouse?.Code}镜种{detail.Lens?.SalesLensCode}度数SPH:{lensDetail.SPH},CYL{lensDetail.CYL}库存片数不足扣库");
                    }
                }
            }
            order.Status = TransferOrderStatusEnum.Receive.ToString();
            order.CheckedBy = _currentUser.Id;
            order.CheckedByName = _currentUser.Name;
            order.CheckedOn = DateTime.Now;
        }
    }
}